#include "show3D.h"



Show3D::Show3D(QWidget * parent)
    : BaseWidget(parent)
{
    m_pointNum  = slt(easyWebServer::Json)["PointNum"].asInt();
    m_sampleStride = slt(easyWebServer::Json)["SampleStride"].asInt();

    m_vtkWidget = new NewVTKOpenGLWidget(parent);
    parent->layout()->addWidget(m_vtkWidget);
    m_vtkPoints = VTK_P(vtkPoints)::New();
    m_vtkPolyData = VTK_P(vtkPolyData)::New();
    m_vtkFilter = VTK_P(vtkVertexGlyphFilter)::New();
    m_vtkMapper = VTK_P(vtkPolyDataMapper)::New();
    m_vtkActor = VTK_P(vtkActor)::New();
    m_vtkRenderer = VTK_P(vtkRenderer)::New();
    m_vtkRendererColorB = VTK_P(vtkRenderer)::New();
    m_vtkDoubleArr = VTK_P(vtkDoubleArray)::New();
    // m_vtkCubeAxesActor = VTK_P(vtkCubeAxesActor)::New();
    m_vtkAxesActor = VTK_P(vtkAxesActor)::New();
    m_vtkOrientWidget = VTK_P(vtkOrientationMarkerWidget)::New();
    m_vtkLookUpTable = VTK_P(vtkLookupTable)::New();
    m_vtkScalarBarActor = VTK_P(vtkScalarBarActor)::New();


    //设置颜色映射的数目
    m_vtkLookUpTable->SetNumberOfTableValues(10);
    m_vtkLookUpTable->SetHueRange(0.0, 0.67);        //色调范围从红色到蓝色
    //设置颜色映射的范围
    m_vtkLookUpTable->SetTableRange(0, 5000);
    m_vtkLookUpTable->Build();

    m_vtkScalarBarActor->SetLookupTable(m_vtkLookUpTable);
    m_vtkScalarBarActor->SetTitle("(mm)");
    m_vtkScalarBarActor->SetWidth(0.05);
    m_vtkScalarBarActor->SetPosition(0.05, 0.1);

    for(int i = 0; i < m_pointNum; i++)
    {
        m_vtkPoints->InsertNextPoint(0, 0, 0);
        m_vtkDoubleArr->InsertNextValue(1.0);
    }
    // m_vtkPoints->Resize(POINTSNUM);
    // m_vtkDoubleArr->Resize(POINTSNUM);
    m_vtkPolyData->SetPoints(m_vtkPoints);
    m_vtkPolyData->GetPointData()->SetScalars(m_vtkDoubleArr);
    m_vtkFilter->SetInputData(m_vtkPolyData);
    m_vtkMapper->SetInputConnection(m_vtkFilter->GetOutputPort());
    m_vtkActor->SetMapper(m_vtkMapper);
    // m_vtkRenderer->AddActor(m_vtkScalarBarActor);
    m_vtkRenderer->AddActor(m_vtkActor);
    m_vtkRenderer->SetLayer(1);
    m_vtkRendererColorB->AddActor(m_vtkScalarBarActor);
    m_vtkRendererColorB->SetLayer(0);
    drawCubePoly();
    m_vtkRenderer->ResetCamera();
    m_vtkRenderer->GetActiveCamera()->SetPosition(CAMERA_DISTANCE, 0, -CAMERA_DISTANCE);
    // m_vtkRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
    // m_vtkRenderer->GetActiveCamera()->SetDistance()
    m_vtkRenderer->GetActiveCamera()->SetViewUp(1, 0, 0);
    m_vtkWidget->GetRenderWindow()->SetNumberOfLayers(2);
    m_vtkWidget->GetRenderWindow()->AddRenderer(m_vtkRendererColorB);
    m_vtkWidget->GetRenderWindow()->AddRenderer(m_vtkRenderer);
	m_vtkOrientWidget->SetOrientationMarker(m_vtkAxesActor);
	m_vtkOrientWidget->SetInteractor(m_vtkWidget->GetRenderWindow()->GetInteractor());
	m_vtkOrientWidget->SetViewport(0.0, 0.0, 0.2, 0.2);
	m_vtkOrientWidget->SetEnabled(1);
	m_vtkOrientWidget->InteractiveOn();
    m_vtkWidget->GetInteractor()->Initialize();
    
}   

Show3D::~Show3D()
{

}

void Show3D::__setData(std::shared_ptr<LvMat> & src, int min, int max)
{
    if(m_isSaveFlag)
    {
        src->saveData<float>(m_filePath + "/CloudPoint.csv");
        m_isSaveFlag = false;
    }
    auto _src = cloudPointDownSample(src, m_sampleStride);
    m_mutex.lock();
    for(int num = 0; num < m_pointNum; num++)
    {
        float x, y, z;
        x = _src->get<float>(num, 0);
        y = _src->get<float>(num, 1);
        z = _src->get<float>(num, 2);
        if((-DISTANCE / 2 < x && x < DISTANCE / 2) && (-DISTANCE / 2 < y && y < DISTANCE / 2) && (0 < z && z < DISTANCE))
        {
            // m_vtkPoints->SetPoint(num, x / -DISTANCE, y / DISTANCE, z / DISTANCE);
            m_vtkPoints->SetPoint(num, x / -1000, y / 1000, z / 1000);
            m_vtkDoubleArr->SetValue(num, z / 5000);
            // m_vtkPoints->InsertNextPoint(x / 500, y / 500, z / 500);
            // m_vtkDoubleArr->InsertNextValue(z / 500);
        }
        else
        {
            m_vtkPoints->SetPoint(num, 0, 0, 0);
            m_vtkDoubleArr->SetValue(num, 1.0);
        }
    }
    m_vtkPoints->Modified();
    m_vtkDoubleArr->Modified();
    m_mutex.unlock();
}

void Show3D::__render()
{
    m_mutex.lock();
    m_vtkWidget->GetRenderWindow()->Render();
    m_mutex.unlock();
}

std::unique_ptr<LvMat> Show3D::cloudPointDownSample(std::shared_ptr<LvMat> & src, int stride)
{
    auto dst = std::make_unique<LvMat>(src->row() / stride, 3, CV_32FC1);
    for(int i = 0; i < dst->row(); i++)
    {
        dst->set<float>(i, 0, src->get<float>(i * stride, 0));
        dst->set<float>(i, 1, src->get<float>(i * stride, 1));
        dst->set<float>(i, 2, src->get<float>(i * stride, 2));
    }
    return std::move(dst);
}

void Show3D::drawCubePoly()
{
	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
	vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
 
	double rangeX[2] = { -1.0, 1.0 };
	double rangeY[2] = { -1.0, 1.0 };
	double intervalX = 0.1, intervalY = 0.1;
 
	// Y lines
	for (double gridX = rangeX[0]; gridX < rangeX[1] + (intervalX / 2.0); gridX += intervalX)
	{
		double lineStart[3] = {0.0, gridX, rangeY[0]};
		double lineEnd[3] = {0.0, gridX, rangeY[1]};
 
		vtkIdType pointIdStart = points->InsertNextPoint(lineStart);
		vtkIdType pointIdEnd = points->InsertNextPoint(lineEnd);
 
		vtkIdType singleLineCell[2] = { pointIdStart, pointIdEnd };
		cells->InsertNextCell(2, singleLineCell);
	}
 
	// x lines
	for (double gridY = rangeY[0]; gridY < rangeY[1] + (intervalY / 2.0); gridY += intervalY)
	{
		double lineStart[3] = {0.0, rangeX[0], gridY};
		double lineEnd[3] = {0.0, rangeX[1], gridY};
 
		vtkIdType pointIdStart = points->InsertNextPoint(lineStart);
		vtkIdType pointIdEnd = points->InsertNextPoint(lineEnd);
 
		vtkIdType singleLineCell[2] = { pointIdStart, pointIdEnd };
		cells->InsertNextCell(2, singleLineCell);
	}
 
	polydata->SetLines(cells);
	polydata->SetPoints(points);
	mapper->SetInputData(polydata);

	vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);
    actor->GetProperty()->SetColor(0.3, 0.3, 0.3);
	// Renderer
	m_vtkRenderer->AddActor(actor);
 
}

void Show3D::__saveData(const std::string & filePath)
{
    m_filePath = filePath;
    m_isSaveFlag = true;
}


